/**
 * https://www.bilibili.com/video/BV1Mb411e7re?p=29
 * DS18B20介绍
 * DS18B20是一种常见的"数字温度传感器"，其控制命令和数据都是以数字信号的方式输入输出，
 * 相比较于"模拟温度传感器"(热敏电阻)，具有功能强大、硬件简单、易扩展、抗干扰性强等特点
 * 测温范围：-55°C 到 +125°C, 最高分辨率: 0.0625°C
 * 通信接口：1-Wire（单总线）
 * 其它特征：可形成总线结构、内置温度报警功能、可寄生供电(数据线+GND, 不要VCC)
 * 
 * 单总线介绍
 * 单总线（1-Wire BUS）是由Dallas公司开发的一种通用数据总线
 * 一根通信线：DQ
 * 异步(没有时钟线)、半双工
 * 单总线只需要一根通信线即可实现数据的双向传输，
 * 当采用寄生供电时，还可以省去设备的VDD线路，此时，供电加通信只需要DQ和GND两根线
 * 
 * https://www.bilibili.com/video/BV1Mb411e7re?p=30
 */
#include <REGX52.H>
#include "Link/Delay_Utils.h"
#include "Link/Single_Keyboard_Utils.h"
// #include "Link/LCD1602_Utils.h"    //2种键盘都和LCD有冲突(P3_4, P3_5), 所以直接使用 UART
#include "Link/Timer0_Utils.h"
#include "Link/UART_Utils.h"
#include "Link/Buzzer_Utils.h"
#include "Link/DS18B20_Utils.h"

static void Timer0_onTick();

static char THigh, TLow;

void main_ds18b20() {
    unsigned char key;
    UART_Init(0, 4800);
    UART_sendString("DS18B20: Temperature Sensor!", 1);

    //转换12位时, 最大转换时间750ms
    DS18B20_Convert_T();
    Delayms(750);
    //Timer0
    Timer0_Init(1000, 0);
    Timer0_setOnTickListener_Exact(1, &Timer0_onTick);

    while (1) {
        key = Single_Keyboard_Down_Timer_Get();
        switch (key) {
            //温度上限, 测温范围：-55°C 到 +125°C, 最高分辨率: 0.0625°C
            case 1: if (THigh < 125) THigh++; break;
            case 2: if (THigh > TLow + 1) THigh--; break;
            //温度下限
            case 3: if (TLow < THigh - 1) TLow++; break;
            case 4: if (TLow > -55) TLow--; break;
            default: break;
        }
    }
}

static void Timer0_onTick() {
    static unsigned char T0Count1, T0Count2;
    static float temperature;
    T0Count1 ++;
    if (T0Count1 >= 255) {
        T0Count1 = 0;
        DS18B20_Convert_T();
        temperature = DS18B20_ReadT();
        UART_sendDouble(1, temperature, 0);
        UART_sendStringFormat(1, " TH:%+bd, TL:%+bd", THigh, TLow);
        // if(temperature < 0) {           //如果温度小于0
        //     UART_sendByte('-');         //显示负号
        //     temperature = -temperature; //将温度变为正数
        // } else {                        //如果温度大于等于0
        //     UART_sendByte('+');         //显示正号
        // }
        // UART_sendNum(temperature, 0);   //显示温度整数部分
        // UART_sendByte('.');              //显示小数点
        // UART_sendNum((unsigned long)(temperature * 10000) % 10000, 1); //显示温度小数部分

        //超出温度范围, 报警
        if (temperature > THigh || temperature < TLow) {
            Buzzer_ring();
        } else Buzzer_stop();
    }

    //独立键盘, 每15ms调用1次
    T0Count2++;
    if (T0Count2 >= 15) {
        T0Count2 = 0;
        Single_Keyboard_Down_Timer(1);
    }
}
